package com.axinfu.util.config.http;

import com.alibaba.fastjson.JSONObject;
import com.axinfu.util.Constant;
import com.axinfu.util.EmptyUtil;
import com.axinfu.util.config.BtgSetPlugin;
import com.axinfu.util.config.util.BtgSetUtils;
import com.axinfu.util.config.util.Utils;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Enumeration;

/**
 * ResourceServlet
 *
 * @author zjn
 * @since 2022/3/24
 */
public class ResourceServlet extends HttpServlet {

    private static final String LOGIN_HTML = "/login.html";
    private static final String LOGIN_JSON = "/login.json";
    private static final String SUFIX_JSON = ".json";
    private static final String SUFIX_HTML = ".html";
    private static final String SUFIX_JPG = ".jpg";
    private static final String SUFIX_PNG = ".png";
    private static final String SUFIX_GIF = ".gif";
    private static final String SUFIX_CSS = ".css";
    private static final String SUFIX_JS = ".js";

    final String keyName = "btgaccess";

    protected final String resourcePath;

    public ResourceServlet(String resourcePath) {
        this.resourcePath = resourcePath;
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        String contextPath = req.getContextPath();
        String servletPath = req.getServletPath();
        String requestUri = req.getRequestURI();

        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");

        // root context
        if (contextPath == null) {
            contextPath = "";
        }
        String uri = contextPath + servletPath;
        String path = requestUri.substring(contextPath.length() + servletPath.length());
        if ("".equals(path)) {
            if ("".equals(contextPath) || Constant.STR_SLASH.equals(contextPath)) {
                resp.sendRedirect("/btgset/login.html");
            } else {
                resp.sendRedirect("btgset/login.html");
            }
            return;
        }

        if (Constant.STR_SLASH.equals(path)) {
            resp.sendRedirect("login.html");
            return;
        }
        if (path.endsWith(LOGIN_HTML)) {
            if (validLogin(req)) {
                resp.sendRedirect("index.html");
                return;
            }
        }
        if (path.contains(SUFIX_JSON)) {
            //验证是否登录
            if (!path.contains(LOGIN_JSON) && !validLogin(req)) {
                JSONObject json = new JSONObject();
                json.put("code", -1);
                json.put("msg", "SessionTimeOut");
                json.put("url", "login.html");
                resp.getWriter().print(json);
                return;
            }
            String fullUrl = path;
            if (req.getQueryString() != null && req.getQueryString().length() > 0) {
                fullUrl += "?" + req.getQueryString();
            }
            JSONObject obj = (JSONObject) process(fullUrl, getParas(req), req, resp);

            if (BtgSetPlugin.getBtgSetPlugin().getIsRefreshSession()) {
                obj.put(keyName, BtgSetUtils.getKey(System.currentTimeMillis()));
                obj.put("key", keyName);
            }
            resp.getWriter().print(obj);
            return;
        }
        returnResourceFile(path, uri, resp);
    }

    protected String getFilePath(String fileName) {
        return resourcePath + fileName;
    }

    protected void returnResourceFile(String fileName, String uri, HttpServletResponse response)
            throws IOException {

        String filePath = getFilePath(fileName);

        if (filePath.endsWith(SUFIX_HTML)) {
            response.setContentType("text/html; charset=utf-8");
        }
        if (fileName.endsWith(SUFIX_JPG) || fileName.endsWith(SUFIX_PNG) || fileName.endsWith(SUFIX_GIF)) {
            byte[] bytes = Utils.readByteArrayFromResource(filePath);
            if (bytes != null) {
                response.getOutputStream().write(bytes);
            }

            return;
        }

        String text = Utils.readFromResource(filePath);
        if (text == null) {
            response.sendRedirect(uri + "/login.html");
            return;
        }
        if (fileName.endsWith(SUFIX_CSS)) {
            response.setContentType("text/css;charset=utf-8");
        } else if (fileName.endsWith(SUFIX_JS)) {
            response.setContentType("text/javascript;charset=utf-8");
        }
        response.getWriter().write(text);
    }

    private JSONObject getParas(HttpServletRequest req) {
        JSONObject object = new JSONObject();

        // 获取request参数
        Enumeration<String> en = req.getParameterNames();
        while (en.hasMoreElements()) {
            String paramName = en.nextElement();
            String paramValue = req.getParameter(paramName);
            object.put(paramName, paramValue);
        }
        return object;
    }

    private Object process(String url, JSONObject params, HttpServletRequest req, HttpServletResponse resp) {

        String methodName = url.substring(url.lastIndexOf("/") + 1, url.indexOf("."));
        try {

            // 利用反射获取方法
            Method method = getClass().getDeclaredMethod(methodName, JSONObject.class, HttpServletRequest.class,
                    HttpServletResponse.class);
            // 执行相应的方法
            return method.invoke(this, params, req, resp);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new JSONObject();
    }

    /**
     * 验证登录是否过期
     *
     * @param req req
     * @return boolean
     */
    private boolean validLogin(HttpServletRequest req) {
        Cookie[] cookies = req.getCookies();
        if (EmptyUtil.isEmpty(cookies)) {
            return false;
        }
        String v = "";
        for (Cookie c : cookies) {
            if (keyName.equals(c.getName())) {
                v = c.getValue();
                break;
            }
        }
        if ("".equals(v)) {
            return false;
        }

        return BtgSetUtils.valid(v);
    }
}
